<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Menus</title>
<link rel="stylesheet" href="/cfg/format.css" type="text/css">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="keywords" content="winapi, Windows API, C, no MFC, menus">
<meta name="description" content="In this part of the Winapi tutorial, we will
work with menus.">
<meta name="language" content="en">
<meta name="author" content="Jan Bodnar">
<meta name="distribution" content="global">

<script type="text/javascript" src="/lib/jquery.js"></script>
<script type="text/javascript" src="/lib/common.js"></script>

</head>

<body>

<div class="container2">

<div id="wide_ad" class="ltow">
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* 160x600, August 2011 */
google_ad_slot = "2484182563";
google_ad_width = 160;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>

<div class="content2">


<a href="../index.html" title="Home">Home</a>&nbsp;
<a href="..">Contents</a>


<h1>Menus</h1>


<p>
In this part of the Winapi tutorial, we will create menus and toolbars. 
A menu is a group of commands located in a menubar. A menubar contains a list of 
menus. Menus can contain either menu items or other menus calls submenus. A menu 
item that carries out a command is called a command item or a command. On 
Windows, menubar is sometimes called a toplevel menu, menus and submenus
are called popup menus. Menu items are usually grouped into some logical groups. 
These groups are divided by a separator. The separator is a small vertical line.
</p>

<div class="big_hor">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-9706709751191532";
/* big_horizontal */
google_ad_slot = "2904953388";
google_ad_width = 728;
google_ad_height = 90;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>


<h2>A simple menu</h2>

<p>
In the following example, we will create a menubar and three menu commands. 
We will also create a separator. 
</p>

<pre class="code">
#include &lt;windows.h&gt;

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void AddMenus(HWND);

#define IDM_FILE_NEW 1
#define IDM_FILE_OPEN 2
#define IDM_FILE_QUIT 3

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PWSTR lpCmdLine, int nCmdShow)
{
  MSG  msg;    
  WNDCLASSW wc = {0};
  wc.lpszClassName = L"Menu";
  wc.hInstance     = hInstance;
  wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
  wc.lpfnWndProc   = WndProc;
  wc.hCursor       = LoadCursor(0, IDC_ARROW);

  RegisterClassW(&wc);
  CreateWindowW(wc.lpszClassName, L"Menu",
                WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                100, 100, 200, 150, 0, 0, hInstance, 0);

  while( GetMessage(&msg, NULL, 0, 0)) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }

  return (int) msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, 
    WPARAM wParam, LPARAM lParam)
{   
  switch(msg)  
  {
      case WM_CREATE:
          AddMenus(hwnd);
          break;

      case WM_COMMAND:
          switch(LOWORD(wParam)) {
              case IDM_FILE_NEW:
              case IDM_FILE_OPEN:
                  Beep(50, 100);
                  break;
              case IDM_FILE_QUIT:
                  SendMessage(hwnd, WM_CLOSE, 0, 0);
                  break;
           }
           break;

      case WM_DESTROY:
          PostQuitMessage(0);
          break;
  }

  return DefWindowProcW(hwnd, msg, wParam, lParam);
}

void AddMenus(HWND hwnd) 
{
  HMENU hMenubar;
  HMENU hMenu;

  hMenubar = CreateMenu();
  hMenu = CreateMenu();

  AppendMenuW(hMenu, MF_STRING, IDM_FILE_NEW, L"&New");
  AppendMenuW(hMenu, MF_STRING, IDM_FILE_OPEN, L"&Open");
  AppendMenuW(hMenu, MF_SEPARATOR, 0, NULL);
  AppendMenuW(hMenu, MF_STRING, IDM_FILE_QUIT, L"&Quit");

  AppendMenuW(hMenubar, MF_POPUP, (UINT_PTR)hMenu, L"&File");
  SetMenu(hwnd, hMenubar);
}
</pre>

<p>
Two menu items will make a short sound. THe third will terminate the 
application.
</p>

<pre class="explanation">
  case WM_COMMAND:
      switch(LOWORD(wParam)) {
          case IDM_FILE_NEW:
          case IDM_FILE_OPEN:
              Beep(50, 100);
              break;
          case IDM_FILE_QUIT:
              SendMessage(hwnd, WM_CLOSE, 0, 0);
              break;
      }
      break;
</pre>

<p>
If we select a menu item, the window procedure receives the 
<code>WM_COMMAND</code> message. The menu item id is in the low order word of 
the wParam value.
</p>


<pre class="explanation">
hMenubar = CreateMenu();
hMenu = CreateMenu();
</pre>

<p>
Menubar and menus are all created using the <code>CreateMenu()</code> 
function call.
</p>

<pre class="explanation">
AppendMenuW(hMenu, MF_STRING, IDM_FILE_NEW, L"&amp;New");
AppendMenuW(hMenu, MF_STRING, IDM_FILE_OPEN, L"&amp;Open");
AppendMenuW(hMenu, MF_SEPARATOR, 0, NULL);
AppendMenuW(hMenu, MF_STRING, IDM_FILE_QUIT, L"&amp;Quit");

AppendMenuW(hMenubar, MF_POPUP, (UINT_PTR)hMenu, L"&amp;File");
</pre>

<p>
Menu items and submenus are created using the <code>AppendMenuW()</code> 
function call. What are we going to append, depends on the flag. 
The <code>MF_STRING</code> appends a label, the <code>MF_SEPARATOR</code> 
appends a separator and the <code>MF_POPUP</code> appends a menu.
</p>

<pre class="explanation">
SetMenu(hwnd, hMenubar);
</pre>

<p>
Finally, we set the menubar calling the <i>SetMenu()</i> function.
</p>

<img src="/img/gui/winapi/simplemenu.png" alt="A menu example">
<div class="figure">Figure: A simple menu</div>


<h2>A popup menu</h2>

<p>
A popup menu is also called context menu. It is a list of commands that appears 
under some context. For example, in a Firefox web browser, when we right click 
on a web page, we get a context menu. Here we can reload a page, go back or 
view page source. If we right click on a toolbar, we get another context menu 
for managing toolbars. 
</p>

<pre class="code">
#include &lt;windows.h&gt;

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

#define IDM_FILE_NEW 1
#define IDM_FILE_OPEN 2
#define IDM_FILE_QUIT 3


int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PWSTR lpCmdLine, int nCmdShow)
{
  MSG  msg;    
  WNDCLASSW wc = {0};
  wc.lpszClassName = L"Application";
  wc.hInstance     = hInstance;
  wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
  wc.lpfnWndProc   = WndProc;
  wc.hCursor       = LoadCursor(0, IDC_ARROW);


  RegisterClassW(&wc);
  CreateWindowW(wc.lpszClassName, L"Popup Menu",
                WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                100, 100, 200, 150, 0, 0, hInstance, 0);

  while( GetMessage(&msg, NULL, 0, 0)) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }

  return (int) msg.wParam;
}

LRESULT CALLBACK WndProc( HWND hwnd, UINT msg,
    WPARAM wParam, LPARAM lParam )
{
  HMENU hMenu;
  POINT point;

  switch(msg)  
  {
    case WM_COMMAND:
        switch(LOWORD(wParam)) {
            case IDM_FILE_NEW:
            case IDM_FILE_OPEN:
                Beep(50, 100);
                break;
            case IDM_FILE_QUIT:
                SendMessage(hwnd, WM_CLOSE, 0, 0);
                break;
        }
        break;

    case WM_RBUTTONUP:
        point.x = LOWORD(lParam);
        point.y = HIWORD(lParam);
        hMenu = CreatePopupMenu();
        ClientToScreen(hwnd, &point);

        AppendMenuW(hMenu, MF_STRING, IDM_FILE_NEW, L"&New");
        AppendMenuW(hMenu, MF_STRING, IDM_FILE_OPEN, L"&Open");
        AppendMenuW(hMenu, MF_SEPARATOR, 0, NULL);
        AppendMenuW(hMenu, MF_STRING, IDM_FILE_QUIT, L"&Quit");
                    
        TrackPopupMenu(hMenu, TPM_RIGHTBUTTON, point.x, point.y, 0, hwnd, NULL);
        DestroyMenu(hMenu);
        break;

    case WM_DESTROY:
        PostQuitMessage(0);
        break;
  }

  return DefWindowProcW(hwnd, msg, wParam, lParam);
}
</pre>

<p>
We have an example with a context menu that has three menu items. 
</p>


<pre class="explanation">
case WM_RBUTTONUP:
    point.x = LOWORD(lParam);
    point.y = HIWORD(lParam);
...    
</pre>

<p>
The <code>WM_RBUTTONUP</code> message is posted when the user releases the right 
mouse button while the cursor is in the client area of a window. The low-order 
word of the lParma  specifies the x-coordinate of the cursor. The high-order 
word specifies the y-coordinate of the cursor. The coordinates are relative to 
the upper-left corner of the client area.
</p>

<pre class="explanation">
hMenu = CreatePopupMenu();   
</pre>

<p>
The <code>CreatePopupMenu()</code> function creates a popup menu. It returns
a handle to the newly created menu. The menu is initially empty.
</p>

<pre class="explanation">
ClientToScreen(hwnd, &point);   
</pre>

<p>
The <code>ClientToScreen()</code> function converts the client coordinates of 
a specified point to screen coordinates. We need these coordinates to display
the context menu.
</p>

<pre class="explanation">
AppendMenuW(hMenu, MF_STRING, IDM_FILE_NEW, L"&New");
AppendMenuW(hMenu, MF_STRING, IDM_FILE_OPEN, L"&Open");
AppendMenuW(hMenu, MF_SEPARATOR, 0, NULL);
AppendMenuW(hMenu, MF_STRING, IDM_FILE_QUIT, L"&Quit");   
</pre>

<p>
Three menu items and one separator are created.
</p>

<pre class="explanation">
TrackPopupMenu(hMenu, TPM_RIGHTBUTTON, point.x, point.y, 0, hwnd, NULL);   
</pre>

<p>
The <code>TrackPopupMenu()</code> function displays a context menu at the 
specified location and tracks the selection of items on the menu.
</p>

<pre class="explanation">
DestroyMenu(hMenu);   
</pre>

<p>
In the end, the menu object is destroyed with the <code>DestroyMenu()</code>
function. A menu that was not assigned to a window must be explicitly destroyed.
</p>

<img src="/img/gui/winapi/popupmenu.png" alt="A popup menu">
<div class="figure">Figure: A popup menu</div>


<h2>A CheckMenuItem</h2>

<p>
A CheckMenuItem is a menu item that has a check mark before
the label of the menu item. A menu item can be checked or unchecked using 
the <code>CheckMenuItem()</code> function.
</p>

<pre class="code">
#include &lt;windows.h&gt;
#include &lt;commctrl.h&gt;

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void AddMenus(HWND);

#define IDM_VIEW_STB 1

HWND ghSb;
HMENU ghMenu;


int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PWSTR lpCmdLine, int nCmdShow)
{
  MSG  msg;    
  WNDCLASSW wc = {0};
  wc.lpszClassName = L"Menu";
  wc.hInstance     = hInstance;
  wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
  wc.lpfnWndProc   = WndProc;
  wc.hCursor       = LoadCursor(0, IDC_ARROW);

  RegisterClassW(&wc);
  CreateWindowW(wc.lpszClassName, L"CheckMenu",
                WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                100, 100, 350, 250, 0, 0, hInstance, 0);

  while( GetMessage(&msg, NULL, 0, 0)) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }

  return (int) msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, 
    WPARAM wParam, LPARAM lParam)
{   
  UINT state;

  switch(msg)  
  {
      case WM_CREATE:
          AddMenus(hwnd);
          
          InitCommonControls();

          ghSb = CreateWindowExW(0, STATUSCLASSNAMEW, NULL, 
              WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, hwnd, 
              (HMENU) 1, GetModuleHandle(NULL), NULL);

          break;

      case WM_COMMAND:
          
          switch(LOWORD(wParam)) {
              case IDM_VIEW_STB:                                    
                  
                  state = GetMenuState(ghMenu, IDM_VIEW_STB, MF_BYCOMMAND); 

                  if (state == SW_SHOWNA) {
                    ShowWindow(ghSb, SW_HIDE);
                    CheckMenuItem(ghMenu, IDM_VIEW_STB, MF_UNCHECKED);  
                  } else {
                    ShowWindow(ghSb, SW_SHOWNA);
                    CheckMenuItem(ghMenu, IDM_VIEW_STB, MF_CHECKED);  
                  }
                  
                  break;
          }
          break;

      case WM_SIZE:
          SendMessage(ghSb, WM_SIZE, wParam, lParam);          
          break;

      case WM_DESTROY:
          PostQuitMessage(0);
          break;
  }

  return DefWindowProcW(hwnd, msg, wParam, lParam);
}


void AddMenus(HWND hwnd) 
{
  HMENU hMenubar;

  hMenubar = CreateMenu();
  ghMenu = CreateMenu();

  AppendMenuW(ghMenu, MF_STRING, IDM_VIEW_STB, L"&Statusbar");
  CheckMenuItem(ghMenu, IDM_VIEW_STB, MF_CHECKED);  

  AppendMenuW(hMenubar, MF_POPUP, (UINT_PTR) ghMenu, L"&View");
  
  SetMenu(hwnd, hMenubar);
}
</pre>

<p>
In the example we have a View menu with one menu item. This menu
item will show/hide a statusbar. When the statusbar is visible, the menu item
is checked. It is unchecked otherwise.
</p>


<pre class="explanation">
#define IDM_VIEW_STB 1
</pre>

<p>
This is an id for the menu item, that will show/hide the statusbar.
</p>

<pre class="explanation">
InitCommonControls();
</pre>

<p>
A statusbar is a common control. It must be initialized with the 
<code>InitCommonControls()</code> function call.
</p>

<pre class="explanation">
ghSb = CreateWindowExW(0, STATUSCLASSNAMEW, NULL, 
    WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, hwnd, 
    (HMENU) 1, GetModuleHandle(NULL), NULL);  
</pre>

<p>
This code creates a statusbar.
</p>


<pre class="explanation">
state = GetMenuState(ghMenu, IDM_VIEW_STB, MF_BYCOMMAND); 
</pre>

<p>
We get the state of the Statusbar menu item. 
</p>

<pre class="explanation">
if (state == SW_SHOWNA) {
  ShowWindow(ghSb, SW_HIDE);
  CheckMenuItem(ghMenu, IDM_VIEW_STB, MF_UNCHECKED);  
} else {
  ShowWindow(ghSb, SW_SHOWNA);
  CheckMenuItem(ghMenu, IDM_VIEW_STB, MF_CHECKED);  
}  
</pre>

<p>
Depending on its state, we show/hide the statusbar control using the 
<code>ShowWindow()</code> function. The menu item is checked/unchecked
accordingly with the <code>CheckMenuItem</code> function.
</p>

<pre class="explanation">
case WM_SIZE:
    SendMessage(ghSb, WM_SIZE, wParam, lParam);          
    break;
</pre>

<p>
We resize the statusbar to fit the window after the window is being resized.
</p>

<img src="/img/gui/winapi/checkmenuitem.png" alt="A CheckMenuItem">
<div class="figure">Figure: A CheckMenuItem</div>


<p>
In this part of the Winapi tutorial, we have covered menus.
</p>

<div class="center"> 
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* horizontal */
google_ad_slot = "1734478269";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script> 
</div> 
<br> 

<div class="botNav, center">
<span class="botNavItem"><a href="/">Home</a></span> ‡ <span class="botNavItem"><a href="..">Contents</a></span>
 ‡ <span class="botNavItem"><a href="#">Top of Page</a></span>
</div>


<div class="footer">
<div class="signature">
<a href="/">ZetCode</a> last modified September 22, 2012  <span class="copyright">&copy; 2007 - 2013 Jan Bodnar</span>
</div>
</div>

</div> <!-- content -->

</div> <!-- container -->

</body>
</html>
